package examle;

import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.ai.attributes.BaseAttributeMap;
import net.minecraft.entity.ai.attributes.IAttributeInstance;
import net.minecraft.util.MathHelper;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author Mega
 * @version 1.0
 * 之后我会将源码上传至 gitee.com
 */
public class TitanKiller {
    //这边提供了几个0血杀泰坦的方法

    //Method1:重新实现setHealth方法
    public static void setLivingHealth(EntityLivingBase livingBase, float health) {
        //我们看一下原版setHealth的实现
        //调用DataWatcher的updateObj
        livingBase.getDataWatcher().updateObject(6, MathHelper.clamp_float(health, 0.0F, livingBase.getMaxHealth()));
    }
    public static void killEntity_1(EntityLivingBase livingBase) {
        setLivingHealth(livingBase, 0.0F);
    }

    //Method2:遍历AttributeInstance设置baseValue
    @SuppressWarnings("ALL")
    public static void killEntity_2(EntityLivingBase livingBase) {
        //反射
        try {
            //获取字段
            Field field = BaseAttributeMap.class.getDeclaredField("field_111154_a");
            //设置访问权限
            field.setAccessible(true);
            //获取值
            Map<Object, Object> map = (Map<Object, Object>) field.get(livingBase.getAttributeMap());
            //遍历keySet
            for (Object key : map.keySet()) {
                //获取实例
                IAttributeInstance attributeInstance = (IAttributeInstance) map.get(key);
                //设置baseValue
                attributeInstance.setBaseValue(0.0D);
            }
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        //这种方法在0.5有用，0.495似乎没有效果
    }

    //Method3:遍历方法自动调用setHealth
    public static void killEntity_3(Object livingBase) {
        //获取实体类
        Class<?> c = livingBase.getClass();
        //这边写一个获取超类的方法
        List<Class<?>> sc = superClasses(c);
        //遍历所有超类
        for (Class<?> clazz : sc) {
            //遍历所有方法
            for (Method m : clazz.getDeclaredMethods()) {
                //判断方法非静态并获取方法名
                if (!Modifier.isStatic(m.getModifiers())) {
                    String methodName = m.getName();
                    //取小写
                    String lower = methodName.toLowerCase();
                    //判断方法是setter且字符串含有health
                    if (lower.contains("set") && lower.contains("health")) {
                        //调用方法
                        try {
                            m.invoke(livingBase, 0.0F);
                        } catch (Throwable e) { e.printStackTrace(); }
                    }
                }
            }
        }
    }

    public static List<Class<?>> superClasses(Class<?> c) {
        List<Class<?>> sc = new ArrayList<Class<?>>();
        sc.add(c);
        Class<?> superClass = c.getSuperclass();
        sc.add(superClass);
        while (superClass.getSuperclass() != Object.class) {
            superClass = superClass.getSuperclass();
            sc.add(superClass);
        }
        return sc;
    }

    //Method4(偏针对性)反向使用heal()方法
    public static void killEntity_4(EntityLivingBase livingBase) {
        //如果你反编译过titan模组的代码你会发现
        //EntityTitan覆写了heal方法
        //覆写后heal并没有检测传入参数为负
        //这样我们传一个-getMaxHealth即可
        livingBase.heal(-livingBase.getMaxHealth() - 114514 - 1919810);
    }
}
